﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.ObjectModel;

namespace dotFitness.Domain
{
    public sealed class WorkoutProgram : EntityBase
    {
        private WorkoutProgram()
        {
            this.Schedule = new ProgramSchedule(this);
            this.Days = new HashSet<ScheduleDayBase>();
        }

        public WorkoutProgram(string name)
            : this()
        {
            ChangeName(name);
        }

        public void ChangeName(string name)
        {
            if (null == name)
                throw new ArgumentNullException("name");

            if (name.Trim() == string.Empty)
                throw new ArgumentException("cannot be empty or whitespace", "name");

            this.Name = name;
        }

        public string Name
        {
            get;
            private set;
        }

        public ProgramSchedule Schedule
        {
            get;
            private set;
        }

        private ICollection<ScheduleDayBase> Days
        {
            get;
            set;
        }

        public sealed class ProgramSchedule
        {
            public ProgramSchedule(WorkoutProgram workoutProgram)
            {
                this.Program = workoutProgram;
            }

            public TrainingDay AddTrainingDay(string name = null)
            {
                var day = new TrainingDay(Program.Days.Count + 1, name);

                Program.Days.Add(day);

                return day;
            }

            public RestDay AddRestDay(string name = null)
            {
                var day = new RestDay(Program.Days.Count + 1, name);

                Program.Days.Add(day);

                return day;
            }

            public CardioDay AddCardioDay(string name = null)
            {
                var day = new CardioDay(Program.Days.Count + 1, name);

                Program.Days.Add(day);

                return day;
            }

            public void RemoveDay(ScheduleDayBase day)
            {
                if (null == day)
                    throw new ArgumentNullException("day");

                if (Program.Days.Contains(day) == false)
                    throw new ArgumentException("day does not belong to schedule", "day");

                Program.Days.Remove(day);
            }

            public void SwapDays(ScheduleDayBase dayA, ScheduleDayBase dayB)
            {
                if (null == dayA)
                    throw new ArgumentNullException("dayA");

                if (null == dayB)
                    throw new ArgumentNullException("dayB");

                if (Program.Days.Contains(dayA) == false)
                    throw new ArgumentException("day does not belong to schedule", "dayA");

                if (Program.Days.Contains(dayB) == false)
                    throw new ArgumentException("day does not belong to schedule", "dayB");

                var beforeDayA = dayA.Day;
                var beforeDayB = dayB.Day;

                dayA.Day = beforeDayB;
                dayB.Day = beforeDayA;
            }

            public IEnumerable<ScheduleDayBase> Days
            {
                get { return this.Program.Days; }
            }

            private WorkoutProgram Program
            {
                get;
                set;
            }
        }
    }
}
